home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_300
/
332_02
/
yahtzee.c
< prev
Wrap
C/C++ Source or Header
|
1990-03-27
|
19KB
|
920 lines
/*- -*- Fundamental -*-
*
* Facility: yahtzee
*
* File: yahtzee.c
*
* Associated files: yahtzee.hlp -- man page
*
* Description: Dice game yahtzee
*
* Portability: Conforms to X/Open Portability Guide, ed. 3,
* I hope ...
*
* Author: Steve Ward
*
* Editor: Anders Thulin
* Rydsvagen 288
* S-582 50 Linkoping
* SWEDEN
*
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*
* Edit history :
*
* Vers Ed Date By Comments
* ---- --- ---------- ---------------- -------------------------------
* 1.0 0 19xx-xx-xx Steve Ward
* 1.1 1 1988-10-25 Anders Thulin Original for H89 computer -
* changed to curses. Cleaned
* up user interface a bit.
*
*/
/* - - Configuration options: - - - - - - - - - - - - - - - - - - - - - - */
/*
* Compile-time environment:
*
* ANSI ANSI C
* BSD BSD Unix, SunOS 3.5
* SV2 AT&T UNIX System V.2
* XPG3 X/Open Portability Guide, ed. 3
* ZTC205 Zortech C 2.05
*
* If you have an ANSI C conformant compiler, use ANSI. Otherwise choose
* the environment that best matches yours.
*
*/
#define ANSI 0
#define BSD 0
#define SV2 0
#define XPG3 0
#define ZTC205 1
/* - - end of configuration - - - - - - - - - - - - - - - - - - - - - - - - */
/* --- Known problems: --------------------------------------------------
curses
Some older implementation of curses dows not have any of the
functions beep(), nodelay() and delay_output().
It may be possible to emulate beep() through calls similar to
fputc(0x07, stderr).
It will, in general, not be possible to emulate nodelay(), as
it changes the behaviour of getch() from blocking to non-blocking(),
that is, if no character is immediately available, return ERR.
delay_output() just waits for a number of seconds. It is only
used in self-play mode, so it can safely be ignored.
------------------------------------------------------------------------*/
#if ANSI
# include <ctype.h>
# include <curses.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
#endif
#if BSD
# include <ctype.h>
# include <curses.h>
# include <string.h>
typedef long time_t;
#endif
#if SV2
# include <ctype.h>
# include <curses.h>
# include <string.h>
typedef long time_t;
#endif
#if XPG3
# include <ctype.h>
# include <curses.h>
# include <stdlib.h>
# include <string.h>
# include <time.h>
#endif
#if ZTC205
# include <ctype.h>
# include <curses.h>
# include <string.h>
# include <time.h>
#endif
/* Command characters used only by auto player: */
#define PASSC -1 /* Accept roll */
#define ROLLC -2
/* Coordinates for screen output - assumes 24 x 80 screen */
#define GOX 45 /* Coordinates for prompt. */
#define GOY 22
#define GAMEY 20
#define SCOREX 30 /* leftmost column for scores */
#define DIEY 22
#define PLAYERS 10 /* Max number of players */
#define NONE (-1) /* illegal value. */
#define TOP 0
#define MID 8
#define BOT 16
/* Various variables: */
int AutoPar[10]; /* heuristic parameters -HA#, -HB#, etc. */
int Dice[5]; /* current roll */
int DTime; /* delay time between moves (in seconds) */
int nplayers; /* number of players */
unsigned rand_seed; /* random number seed */
int ShowTot;
char Potent[13]; /* Potential score... */
char PotKind, PotSum, PotStr; /* Filled by Pot */
char PotMax, PotCnt;
int *ShowSc;
char ShowX, ShowY;
struct Player {
int Scores[13]; /* Scores, or 127 iff none yet. */
int Select; /* Currently selected category. */
int Col; /* Column number, for scores. */
char Name[40]; /* Name of player. */
int Total; /* total score. */
int Games;
} Who[PLAYERS];
/* Local routines: */
#if __STDC__
int Auto(int pl, int rolls);
void Bd(int f);
void Board(void);
void Center(char *text, int centx, int y, int xsize);
int Cycle(int pl, int delta);
void Delay(int sec);
void Die(int number, int count);
int Go(int rolls, int player);
void iplayer(char *name, struct Player *pl);
int Kind(int die);
void Play(int pl);
void Pot(int pl);
void Roll(void);
void Show(int pl);
void Show1(int n, int flag);
int Straight(int die);
#else
int Auto();
void Bd();
void Board();
void Center();
int Cycle();
void Delay();
void Die();
int Go();
void iplayer();
int Kind();
void Play();
void Pot();
void Roll();
void Show();
void Show1();
int Straight();
#endif
/*
* Routine: Auto
*
* Description: Make move for a computer player.
*
* Note that the routine handles selection of dice
* to reroll internally, without bothering to
* go through 'Go()'.
*
* Strategy is somewhat unclear.
*
*/
int Auto(pl, rolls)
int pl;
char rolls;
{
int choice;
int i;
int *sc;
char gofor, j;
int value[13], target[6], best, n;
sc = Who[pl].Scores;
Pot(pl);
mvaddstr(GOY+1, GOX, "Hmmm ... lemme think."); clrtoeol();
Delay(DTime);
for (i=0; i<13; i++) {
if (sc[i] != NONE) value[i] = i-99;
else if (i<6) value[i] = 2*(Potent[i]-3*(i+1));/* face counts */
else if (i==6) value[i] = Potent[i]-20; /* 3 of a kind */
else if (i==7) value[i] = Potent[i]-15; /* 4 of a kind */
else if (i==9) value[i] = Potent[i]-12; /* 4 straight */
else if (i==10) value[i] = Potent[i]-10; /* 5 straight */
else if (i==12) value[i] = Potent[i]-21-AutoPar[5]; /* CHANCE */
else value[i] = Potent[i]-10;
}
for (i=0; i<6; i++) {
if (sc[12] == NONE) target[i] = i+i; else target[i] = 0;
if (sc[i] == NONE) target[i] += i<<2; else target[i] -= 15;
if ((sc[8] == NONE) && (Kind(i+1) == 3)) target[i] += 6;
if (sc[11] == NONE) target[i] += 1<<(Kind(i+1));
target[i] += Kind(i+1)<<3;
}
best = -99; gofor = PotCnt; choice = Who[pl].Select;
for (i=0; i<13; i++) {
if (value[i] > best) {
best = value[i]; choice = i;
}
}
Who[pl].Select = choice;
Show(pl);
if (rolls && /* Convert a straight?? */
(Potent[9] > 0) &&
(Potent[10] == 0) &&
(sc[10] == NONE)) {
for (i=0; i<5; i++) { /* Find the useless die. */
j = Dice[i];
Dice[i] = 0;
Pot(pl);
Dice[i] = j;
if (Potent[9] > 0) {
Die(i, 0);
goto rollit;
}
}
}
Pot(pl);
if ((choice > 7) && (choice < 12)) goto hit; /* End the inning. */
if (rolls) {
for (i=0; i<6; i++) {
if ((n=(target[i]-27-AutoPar[0])) > best) {
gofor = i;
choice = 255;
best=n;
}
}
}
if ((choice == 255) || (choice < 8))
goto maxim; /* See if we can help. */
if (!rolls) goto hit; /* Least of evils... */
for (i=0; i<5; i++) Die(i,0); /* Re-roll entire hand. */
goto rollit;
maxim:
if (!rolls) goto hit; /* Maximize number of chosen dice. */
for (i=0; i<5; i++)
if (Dice[i] && (Dice[i] != (gofor+1)))
Die(i, 0);
rollit:
move(GOY+1, GOX);
printw("Baby needs shoes ... %d/%d", choice, best);
clrtoeol();
Delay(DTime/2);
return ROLLC;
hit:
move(GOY+1, GOX);
printw("I've decided ... %d/%d", choice, best);
clrtoeol();
Delay(DTime);
return PASSC;
}
/*
* Routine: Bd
*
* Description: Display empty board line. Type of line depends
* on argument.
*
*/
void Bd(f)
int f;
{
char *cc;
int i;
cc = " . ";
if (f == 1) {
cc = "===";
} else if (!f) {
#if 0
puts("\033q"); /* normal mode */
#endif
}
for (i=((COLS-SCOREX)/3); i--;) {
addstr(cc);
}
#if 0
puts("\033p\033G"); /* inverse mode, no graphics */
#endif
}
/*
* Routine: Board
*
* Description: Print empty score-sheet
*
*/
void Board()
{
int i;
clear();
addstr(" YAHTZEE 1.1 ");
for (i=48; i--;) {
addch('=');
}
move( 1, 0); addstr(" ACES ADD 1's "); B